package com.legendframework.core.dao.transaction;

import com.legendframework.core.dao.DataResources;
import com.legendframework.core.dao.exception.DaoException;
import com.legendframework.core.dao.transaction.enums.TransactionStatus;
import com.legendframework.core.dao.transaction.pojo.SqlTransaction;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.UUID;

public class JdbcTransaction extends AbstractTransaction<Deque<SqlTransaction>> {

    private final DataResources dataResources;

    public JdbcTransaction(DataResources dataResources){
        super();
        this.dataResources = dataResources;
    }

    @Override
    public Deque<SqlTransaction> getThreadLocalData() {
        Deque<SqlTransaction> ioTransactions = super.threadLocal.get();
        if (ioTransactions == null) {
            super.threadLocal.set(ioTransactions = new LinkedList<>());
        }
        return ioTransactions;
    }

    @Override
    public void start() {
        //获取数据源
        DataSource dataSource = dataResources.getDataSource();
        //创建事务
        SqlTransaction sqlTransaction = new SqlTransaction();
        sqlTransaction.setId(UUID.randomUUID().toString().replace("-",""));
        sqlTransaction.setStatus(TransactionStatus.BIGIN);
        try {
            sqlTransaction.setConnection(dataSource.getConnection());
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("数据库连接获取失败");
        }
        try {
            //设置为不自动提交
            sqlTransaction.getConnection().setAutoCommit(false);
            //事务进栈
            getThreadLocalData().push(sqlTransaction);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("数据库开启事务失败");
        }
    }

    @Override
    public void commit() {
        //获取当前事务
        SqlTransaction sqlTransaction = getThreadLocalData().peek();
        if (sqlTransaction == null) {
            return;
        }
        try {
            //手动提交
            sqlTransaction.getConnection().commit();
            //恢复自动提交
            sqlTransaction.getConnection().setAutoCommit(true);
            //关闭连接
            sqlTransaction.getConnection().close();
            //事务出栈
            getThreadLocalData().poll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void back() {
        //获取当前事务
        SqlTransaction sqlTransaction = getThreadLocalData().peek();
        if (sqlTransaction == null) {
            return;
        }
        try {
            //回滚
            sqlTransaction.getConnection().rollback();
            //恢复自动提交
            sqlTransaction.getConnection().setAutoCommit(true);
            //关闭连接
            sqlTransaction.getConnection().close();
            //事务出栈
            getThreadLocalData().poll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 校验线程变量中的参数
     * @return
     */
    protected boolean check(){
        if (dataResources == null || dataResources.getDataSource() == null) {
            return false;
        }
        return true;
    }

    @Override
    public void onMount() {
        //获取当前事务
        SqlTransaction peek = getThreadLocalData().peek();
        if (peek != null && peek.getStatus() == TransactionStatus.BIGIN) {
            peek.setStatus(TransactionStatus.NOT);
        }
    }

    @Override
    public void onRecovery() {
        //获取当前事务
        SqlTransaction peek = getThreadLocalData().peek();
        if (peek != null && peek.getStatus() == TransactionStatus.BIGIN) {
            peek.setStatus(TransactionStatus.BIGIN);
        }
    }
}
